﻿using System;
using System.Windows;
using System.Collections.Generic;

namespace SBPweb.PROvibe.Shared.Actors
{

    public class AncestorTree<TElement> 
        where TElement : FrameworkElement
    {

        private AncestorTreeNode<TElement> rootNode;

        public AncestorTreeNode<TElement> RootNode
        {
            get
            {
                return rootNode;
            }
        }

        public void MergeNodes(AncestorTreeNode<TElement> atn)
        {
            AncestorTreeNode<TElement> foundRoot = FindRoot(atn);
            if (rootNode == null)
            {
                rootNode = foundRoot;
                return;
            }
            MergeNodes(rootNode, foundRoot);
        }

        private void MergeNodes(AncestorTreeNode<TElement> rootNode, AncestorTreeNode<TElement> node)
        {
            if (rootNode.Element == node.Element)
            {
                rootNode.Children.AddRange(node.Children);
            }
            foreach (AncestorTreeNode<TElement> item in rootNode.Children)
            {
                MergeNodes(item, node);
            }
        }

        private AncestorTreeNode<TElement> FindRoot(AncestorTreeNode<TElement> atn)
        {
            if (atn == null)
            {
                return null;
            }
            AncestorTreeNode<TElement> parent = FindRoot(atn.Parent);
            if (parent == null)
            {
                return atn;
            }
            return parent;
        }

        public AncestorTreeNode<TElement> FindElementRecursively<TMember>(TMember value, ElementMemberComparison<TMember> comparison)
        {
            return AncestorTree<TElement>.FindElementRecursively<TMember>(rootNode, value, comparison);
        }

        public static AncestorTreeNode<TElement> FindElementRecursively<TMember>(AncestorTreeNode<TElement> element, TMember value, ElementMemberComparison<TMember> comparison)
        {
            if (comparison.Invoke(element, value))
            {
                return element;
            }
            foreach (AncestorTreeNode<TElement> atn in element.Children)
            {
                return FindElementRecursively<TMember>(atn, value, comparison);
                //AncestorTreeNode<TElement> e;
                //if ((e = FindElementRecursively<TMember>(atn, value, comparison)) != default(TElement))
                //{
                //    return e;
                //}
            }
            return default(AncestorTreeNode<TElement>);
        }

        public delegate bool ElementMemberComparison<TMember>(AncestorTreeNode<TElement> element, TMember member);


    }

}